1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.nio.cs.ext;
27
28 import java.nio.ByteBuffer;
29 import java.nio.CharBuffer;
30 import java.nio.charset.Charset;
31 import java.nio.charset.CharsetDecoder;
32 import java.nio.charset.CharsetEncoder;
33 import java.nio.charset.CoderResult;
34 import java.util.Arrays;
35 import sun.nio.cs.Surrogate;
36 import static sun.nio.cs.CharsetMapping.*;
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 public class DoubleByte {
102
103 public final static char[] B2C_UNMAPPABLE;
104 static {
105 B2C_UNMAPPABLE = new char[0x100];
106 Arrays.fill(B2C_UNMAPPABLE, UNMAPPABLE_DECODING);
107 }
108
109 public static class Decoder extends CharsetDecoder
110 implements DelegatableDecoder
111 {
112
113 final char[][] b2c;
114 final char[] b2cSB;
115 final int b2Min;
116 final int b2Max;
117
118
119 protected CoderResult crMalformedOrUnderFlow(int b) {
120 return CoderResult.UNDERFLOW;
121 }
122
123 protected CoderResult crMalformedOrUnmappable(int b) {
124 return CoderResult.unmappableForLength(2);
125 }
126
127 Decoder(Charset cs, float avgcpb, float maxcpb,
128 char[][] b2c, char[] b2cSB,
129 int b2Min, int b2Max) {
130 super(cs, avgcpb, maxcpb);
131 this.b2c = b2c;
132 this.b2cSB = b2cSB;
133 this.b2Min = b2Min;
134 this.b2Max = b2Max;
135 }
136
137 Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
138 this(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);
139 }
140
141 protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
142 byte[] sa = src.array();
143 int sp = src.arrayOffset() + src.position();
144 int sl = src.arrayOffset() + src.limit();
145
146 char[] da = dst.array();
147 int dp = dst.arrayOffset() + dst.position();
148 int dl = dst.arrayOffset() + dst.limit();
149
150 try {
151 while (sp < sl && dp < dl) {
152
153 int inSize = 1;
154 int b1 = sa[sp] & 0xff;
155 char c = b2cSB[b1];
156 if (c == UNMAPPABLE_DECODING) {
157 if (sl - sp < 2)
158 return crMalformedOrUnderFlow(b1);
159 int b2 = sa[sp + 1] & 0xff;
160 if (b2 < b2Min || b2 > b2Max ||
161 (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
162 return crMalformedOrUnmappable(b1);
163 }
164 inSize++;
165 }
166 da[dp++] = c;
167 sp += inSize;
168 }
169 return (sp >= sl) ? CoderResult.UNDERFLOW
170 : CoderResult.OVERFLOW;
171 } finally {
172 src.position(sp - src.arrayOffset());
173 dst.position(dp - dst.arrayOffset());
174 }
175 }
176
177 protected CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
178 int mark = src.position();
179 try {
180
181 while (src.hasRemaining() && dst.hasRemaining()) {
182 int b1 = src.get() & 0xff;
183 char c = b2cSB[b1];
184 int inSize = 1;
185 if (c == UNMAPPABLE_DECODING) {
186 if (src.remaining() < 1)
187 return crMalformedOrUnderFlow(b1);
188 int b2 = src.get() & 0xff;
189 if (b2 < b2Min || b2 > b2Max ||
190 (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING)
191 return crMalformedOrUnmappable(b1);
192 inSize++;
193 }
194 dst.put(c);
195 mark += inSize;
196 }
197 return src.hasRemaining()? CoderResult.OVERFLOW
198 : CoderResult.UNDERFLOW;
199 } finally {
200 src.position(mark);
201 }
202 }
203
204
205 public CoderResult decodeLoop(ByteBuffer src, CharBuffer dst) {
206 if (src.hasArray() && dst.hasArray())
207 return decodeArrayLoop(src, dst);
208 else
209 return decodeBufferLoop(src, dst);
210 }
211
212 public void implReset() {
213 super.implReset();
214 }
215
216 public CoderResult implFlush(CharBuffer out) {
217 return super.implFlush(out);
218 }
219
220
221
222 public char decodeSingle(int b) {
223 return b2cSB[b];
224 }
225
226 public char decodeDouble(int b1, int b2) {
227 if (b2 < b2Min || b2 > b2Max)
228 return UNMAPPABLE_DECODING;
229 return b2c[b1][b2 - b2Min];
230 }
231 }
232
233
234 public static class Decoder_EBCDIC extends Decoder {
235 private static final int SBCS = 0;
236 private static final int DBCS = 1;
237 private static final int SO = 0x0e;
238 private static final int SI = 0x0f;
239 private int currentState;
240
241 Decoder_EBCDIC(Charset cs,
242 char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
243 super(cs, b2c, b2cSB, b2Min, b2Max);
244 }
245
246 public void implReset() {
247 currentState = SBCS;
248 }
249
250
251
252
253
254
255
256
257
258
259
260
261
262 private static boolean isDoubleByte(int b1, int b2) {
263 return (0x41 <= b1 && b1 <= 0xfe && 0x41 <= b2 && b2 <= 0xfe)
264 || (b1 == 0x40 && b2 == 0x40);
265 }
266
267 protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
268 byte[] sa = src.array();
269 int sp = src.arrayOffset() + src.position();
270 int sl = src.arrayOffset() + src.limit();
271 char[] da = dst.array();
272 int dp = dst.arrayOffset() + dst.position();
273 int dl = dst.arrayOffset() + dst.limit();
274
275 try {
276
277
278 while (sp < sl) {
279 int b1 = sa[sp] & 0xff;
280 int inSize = 1;
281 if (b1 == SO) {
282 if (currentState != SBCS)
283 return CoderResult.malformedForLength(1);
284 else
285 currentState = DBCS;
286 } else if (b1 == SI) {
287 if (currentState != DBCS)
288 return CoderResult.malformedForLength(1);
289 else
290 currentState = SBCS;
291 } else {
292 char c = UNMAPPABLE_DECODING;
293 if (currentState == SBCS) {
294 c = b2cSB[b1];
295 if (c == UNMAPPABLE_DECODING)
296 return CoderResult.unmappableForLength(1);
297 } else {
298 if (sl - sp < 2)
299 return CoderResult.UNDERFLOW;
300 int b2 = sa[sp + 1] & 0xff;
301 if (b2 < b2Min || b2 > b2Max ||
302 (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
303 if (!isDoubleByte(b1, b2))
304 return CoderResult.malformedForLength(2);
305 return CoderResult.unmappableForLength(2);
306 }
307 inSize++;
308 }
309 if (dl - dp < 1)
310 return CoderResult.OVERFLOW;
311
312 da[dp++] = c;
313 }
314 sp += inSize;
315 }
316 return CoderResult.UNDERFLOW;
317 } finally {
318 src.position(sp - src.arrayOffset());
319 dst.position(dp - dst.arrayOffset());
320 }
321 }
322
323 protected CoderResult decodeBufferLoop(ByteBuffer src, CharBuffer dst) {
324 int mark = src.position();
325 try {
326 while (src.hasRemaining()) {
327 int b1 = src.get() & 0xff;
328 int inSize = 1;
329 if (b1 == SO) {
330 if (currentState != SBCS)
331 return CoderResult.malformedForLength(1);
332 else
333 currentState = DBCS;
334 } else if (b1 == SI) {
335 if (currentState != DBCS)
336 return CoderResult.malformedForLength(1);
337 else
338 currentState = SBCS;
339 } else {
340 char c = UNMAPPABLE_DECODING;
341 if (currentState == SBCS) {
342 c = b2cSB[b1];
343 if (c == UNMAPPABLE_DECODING)
344 return CoderResult.unmappableForLength(1);
345 } else {
346 if (src.remaining() < 1)
347 return CoderResult.UNDERFLOW;
348 int b2 = src.get()&0xff;
349 if (b2 < b2Min || b2 > b2Max ||
350 (c = b2c[b1][b2 - b2Min]) == UNMAPPABLE_DECODING) {
351 if (!isDoubleByte(b1, b2))
352 return CoderResult.malformedForLength(2);
353 return CoderResult.unmappableForLength(2);
354 }
355 inSize++;
356 }
357
358 if (dst.remaining() < 1)
359 return CoderResult.OVERFLOW;
360
361 dst.put(c);
362 }
363 mark += inSize;
364 }
365 return CoderResult.UNDERFLOW;
366 } finally {
367 src.position(mark);
368 }
369 }
370 }
371
372
373 public static class Decoder_EBCDIC_DBCSONLY extends Decoder {
374 static final char[] b2cSB;
375 static {
376 b2cSB = new char[0x100];
377 Arrays.fill(b2cSB, UNMAPPABLE_DECODING);
378 }
379 Decoder_EBCDIC_DBCSONLY(Charset cs, char[][] b2c, int b2Min, int b2Max) {
380 super(cs, 0.5f, 1.0f, b2c, b2cSB, b2Min, b2Max);
381 }
382 }
383
384
385
386
387 public static class Decoder_EUC_SIM extends Decoder {
388 private final int SS2 = 0x8E;
389 private final int SS3 = 0x8F;
390
391 Decoder_EUC_SIM(Charset cs,
392 char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
393 super(cs, b2c, b2cSB, b2Min, b2Max);
394 }
395
396
397 protected CoderResult crMalformedOrUnderFlow(int b) {
398 if (b == SS2 || b == SS3 )
399 return CoderResult.malformedForLength(1);
400 return CoderResult.UNDERFLOW;
401 }
402
403 protected CoderResult crMalformedOrUnmappable(int b) {
404 if (b == SS2 || b == SS3 )
405 return CoderResult.malformedForLength(1);
406 return CoderResult.unmappableForLength(2);
407 }
408 }
409
410 public static class Encoder extends CharsetEncoder {
411 final int MAX_SINGLEBYTE = 0xff;
412 private final char[] c2b;
413 private final char[] c2bIndex;
414 Surrogate.Parser sgp;
415
416 protected Encoder(Charset cs, char[] c2b, char[] c2bIndex) {
417 super(cs, 2.0f, 2.0f);
418 this.c2b = c2b;
419 this.c2bIndex = c2bIndex;
420 }
421
422 Encoder(Charset cs, float avg, float max, byte[] repl, char[] c2b, char[] c2bIndex) {
423 super(cs, avg, max, repl);
424 this.c2b = c2b;
425 this.c2bIndex = c2bIndex;
426 }
427
428 public boolean canEncode(char c) {
429 return encodeChar(c) != UNMAPPABLE_ENCODING;
430 }
431
432 Surrogate.Parser sgp() {
433 if (sgp == null)
434 sgp = new Surrogate.Parser();
435 return sgp;
436 }
437
438 protected CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
439 char[] sa = src.array();
440 int sp = src.arrayOffset() + src.position();
441 int sl = src.arrayOffset() + src.limit();
442
443 byte[] da = dst.array();
444 int dp = dst.arrayOffset() + dst.position();
445 int dl = dst.arrayOffset() + dst.limit();
446
447 try {
448 while (sp < sl) {
449 char c = sa[sp];
450 int bb = encodeChar(c);
451 if (bb == UNMAPPABLE_ENCODING) {
452 if (Character.isSurrogate(c)) {
453 if (sgp().parse(c, sa, sp, sl) < 0)
454 return sgp.error();
455 return sgp.unmappableResult();
456 }
457 return CoderResult.unmappableForLength(1);
458 }
459
460 if (bb > MAX_SINGLEBYTE) {
461 if (dl - dp < 2)
462 return CoderResult.OVERFLOW;
463 da[dp++] = (byte)(bb >> 8);
464 da[dp++] = (byte)bb;
465 } else {
466 if (dl - dp < 1)
467 return CoderResult.OVERFLOW;
468 da[dp++] = (byte)bb;
469 }
470
471 sp++;
472 }
473 return CoderResult.UNDERFLOW;
474 } finally {
475 src.position(sp - src.arrayOffset());
476 dst.position(dp - dst.arrayOffset());
477 }
478 }
479
480 protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
481 int mark = src.position();
482 try {
483 while (src.hasRemaining()) {
484 char c = src.get();
485 int bb = encodeChar(c);
486 if (bb == UNMAPPABLE_ENCODING) {
487 if (Character.isSurrogate(c)) {
488 if (sgp().parse(c, src) < 0)
489 return sgp.error();
490 return sgp.unmappableResult();
491 }
492 return CoderResult.unmappableForLength(1);
493 }
494 if (bb > MAX_SINGLEBYTE) {
495 if (dst.remaining() < 2)
496 return CoderResult.OVERFLOW;
497 dst.put((byte)(bb >> 8));
498 dst.put((byte)(bb));
499 } else {
500 if (dst.remaining() < 1)
501 return CoderResult.OVERFLOW;
502 dst.put((byte)bb);
503 }
504 mark++;
505 }
506 return CoderResult.UNDERFLOW;
507 } finally {
508 src.position(mark);
509 }
510 }
511
512 protected CoderResult encodeLoop(CharBuffer src, ByteBuffer dst) {
513 if (src.hasArray() && dst.hasArray())
514 return encodeArrayLoop(src, dst);
515 else
516 return encodeBufferLoop(src, dst);
517 }
518
519 public int encodeChar(char ch) {
520 return c2b[c2bIndex[ch >> 8] + (ch & 0xff)];
521 }
522
523
524 static void initC2B(String[] b2c, String b2cSB, String b2cNR, String c2bNR,
525 int b2Min, int b2Max,
526 char[] c2b, char[] c2bIndex)
527 {
528 Arrays.fill(c2b, (char)UNMAPPABLE_ENCODING);
529 int off = 0x100;
530
531 char[][] b2c_ca = new char[b2c.length][];
532 char[] b2cSB_ca = null;
533 if (b2cSB != null)
534 b2cSB_ca = b2cSB.toCharArray();
535
536 for (int i = 0; i < b2c.length; i++) {
537 if (b2c[i] == null)
538 continue;
539 b2c_ca[i] = b2c[i].toCharArray();
540 }
541
542 if (b2cNR != null) {
543 int j = 0;
544 while (j < b2cNR.length()) {
545 char b = b2cNR.charAt(j++);
546 char c = b2cNR.charAt(j++);
547 if (b < 0x100 && b2cSB_ca != null) {
548 if (b2cSB_ca[b] == c)
549 b2cSB_ca[b] = UNMAPPABLE_DECODING;
550 } else {
551 if (b2c_ca[b >> 8][(b & 0xff) - b2Min] == c)
552 b2c_ca[b >> 8][(b & 0xff) - b2Min] = UNMAPPABLE_DECODING;
553 }
554 }
555 }
556
557 if (b2cSB_ca != null) {
558 for (int b = 0; b < b2cSB_ca.length; b++) {
559 char c = b2cSB_ca[b];
560 if (c == UNMAPPABLE_DECODING)
561 continue;
562 int index = c2bIndex[c >> 8];
563 if (index == 0) {
564 index = off;
565 off += 0x100;
566 c2bIndex[c >> 8] = (char)index;
567 }
568 c2b[index + (c & 0xff)] = (char)b;
569 }
570 }
571
572 for (int b1 = 0; b1 < b2c.length; b1++) {
573 char[] db = b2c_ca[b1];
574 if (db == null)
575 continue;
576 for (int b2 = b2Min; b2 <= b2Max; b2++) {
577 char c = db[b2 - b2Min];
578 if (c == UNMAPPABLE_DECODING)
579 continue;
580 int index = c2bIndex[c >> 8];
581 if (index == 0) {
582 index = off;
583 off += 0x100;
584 c2bIndex[c >> 8] = (char)index;
585 }
586 c2b[index + (c & 0xff)] = (char)((b1 << 8) | b2);
587 }
588 }
589
590 if (c2bNR != null) {
591
592 for (int i = 0; i < c2bNR.length(); i += 2) {
593 char b = c2bNR.charAt(i);
594 char c = c2bNR.charAt(i + 1);
595 int index = (c >> 8);
596 if (c2bIndex[index] == 0) {
597 c2bIndex[index] = (char)off;
598 off += 0x100;
599 }
600 index = c2bIndex[index] + (c & 0xff);
601 c2b[index] = b;
602 }
603 }
604 }
605 }
606
607
608 public static class Encoder_EBCDIC_DBCSONLY extends Encoder {
609 Encoder_EBCDIC_DBCSONLY(Charset cs, byte[] repl,
610 char[] c2b, char[] c2bIndex) {
611 super(cs, 2.0f, 2.0f, repl, c2b, c2bIndex);
612 }
613
614 public int encodeChar(char ch) {
615 int bb = super.encodeChar(ch);
616 if (bb <= MAX_SINGLEBYTE)
617 return UNMAPPABLE_ENCODING;
618 return bb;
619 }
620 }
621
622
623 public static class Encoder_EBCDIC extends Encoder {
624 static final int SBCS = 0;
625 static final int DBCS = 1;
626 static final byte SO = 0x0e;
627 static final byte SI = 0x0f;
628
629 protected int currentState = SBCS;
630
631 Encoder_EBCDIC(Charset cs, char[] c2b, char[] c2bIndex) {
632 super(cs, 4.0f, 5.0f, new byte[] {(byte)0x6f}, c2b, c2bIndex);
633 }
634
635 protected void implReset() {
636 currentState = SBCS;
637 }
638
639 protected CoderResult implFlush(ByteBuffer out) {
640 if (currentState == DBCS) {
641 if (out.remaining() < 1)
642 return CoderResult.OVERFLOW;
643 out.put(SI);
644 }
645 implReset();
646 return CoderResult.UNDERFLOW;
647 }
648
649 protected CoderResult encodeArrayLoop(CharBuffer src, ByteBuffer dst) {
650 char[] sa = src.array();
651 int sp = src.arrayOffset() + src.position();
652 int sl = src.arrayOffset() + src.limit();
653 byte[] da = dst.array();
654 int dp = dst.arrayOffset() + dst.position();
655 int dl = dst.arrayOffset() + dst.limit();
656
657 try {
658 while (sp < sl) {
659 char c = sa[sp];
660 int bb = encodeChar(c);
661 if (bb == UNMAPPABLE_ENCODING) {
662 if (Character.isSurrogate(c)) {
663 if (sgp().parse(c, sa, sp, sl) < 0)
664 return sgp.error();
665 return sgp.unmappableResult();
666 }
667 return CoderResult.unmappableForLength(1);
668 }
669 if (bb > MAX_SINGLEBYTE) {
670 if (currentState == SBCS) {
671 if (dl - dp < 1)
672 return CoderResult.OVERFLOW;
673 currentState = DBCS;
674 da[dp++] = SO;
675 }
676 if (dl - dp < 2)
677 return CoderResult.OVERFLOW;
678 da[dp++] = (byte)(bb >> 8);
679 da[dp++] = (byte)bb;
680 } else {
681 if (currentState == DBCS) {
682 if (dl - dp < 1)
683 return CoderResult.OVERFLOW;
684 currentState = SBCS;
685 da[dp++] = SI;
686 }
687 if (dl - dp < 1)
688 return CoderResult.OVERFLOW;
689 da[dp++] = (byte)bb;
690
691 }
692 sp++;
693 }
694 return CoderResult.UNDERFLOW;
695 } finally {
696 src.position(sp - src.arrayOffset());
697 dst.position(dp - dst.arrayOffset());
698 }
699 }
700
701 protected CoderResult encodeBufferLoop(CharBuffer src, ByteBuffer dst) {
702 int mark = src.position();
703 try {
704 while (src.hasRemaining()) {
705 char c = src.get();
706 int bb = encodeChar(c);
707 if (bb == UNMAPPABLE_ENCODING) {
708 if (Character.isSurrogate(c)) {
709 if (sgp().parse(c, src) < 0)
710 return sgp.error();
711 return sgp.unmappableResult();
712 }
713 return CoderResult.unmappableForLength(1);
714 }
715 if (bb > MAX_SINGLEBYTE) {
716 if (currentState == SBCS) {
717 if (dst.remaining() < 1)
718 return CoderResult.OVERFLOW;
719 currentState = DBCS;
720 dst.put(SO);
721 }
722 if (dst.remaining() < 2)
723 return CoderResult.OVERFLOW;
724 dst.put((byte)(bb >> 8));
725 dst.put((byte)(bb));
726 } else {
727 if (currentState == DBCS) {
728 if (dst.remaining() < 1)
729 return CoderResult.OVERFLOW;
730 currentState = SBCS;
731 dst.put(SI);
732 }
733 if (dst.remaining() < 1)
734 return CoderResult.OVERFLOW;
735 dst.put((byte)bb);
736 }
737 mark++;
738 }
739 return CoderResult.UNDERFLOW;
740 } finally {
741 src.position(mark);
742 }
743 }
744 }
745
746
747 public static class Encoder_EUC_SIM extends Encoder {
748 Encoder_EUC_SIM(Charset cs, char[] c2b, char[] c2bIndex) {
749 super(cs, c2b, c2bIndex);
750 }
751 }
752 }